String.prototype.replaceAll = function(s1, s2) {
    return this.replace(new RegExp(s1, "gm"), s2);
}
var Q = {}
Q.ie = (navigator.userAgent.toLowerCase().indexOf("msie") != -1);
Q.ff = (navigator.userAgent.toLowerCase().indexOf("firefox") != -1);
Q.get = function(id) {
    if (!id || id == null || id == "") return null;
    if (typeof(id) == "object") {return id;}
    var com = document.getElementById(id);
    if (!com) com = document.getElementsByName(id)[0];
    return com;
}
Q.debugId = null;
Q.debugZone = null;
Q.debugCount = 0;
Q.debugStyleClassTime = "red";
Q.debugStyleClassInfo = "red";
Q.setDebugId = function(debugId, styleClassTime, styleClassInfo) {
    if (debugId == "") return;
    this.debugId = debugId;
    if (styleClassTime != null)
        this.debugStyleClassTime = styleClassTime;
    if (styleClassInfo != null)
        this.debugStyleClassInfo = styleClassInfo;
}
Q.debug = function(message) {
    if (this.debugZone == null && this.debugId != null)
        this.debugZone = Q.get(this.debugId);
    if (this.debugZone != null) {
        var obj = document.createElement("div");
        var rowCount = document.createElement("span");
        var timeZone = document.createElement("span");
        var infoZone = document.createElement("span");
        rowCount.innerHTML = ++Q.debugCount;
        timeZone.innerHTML = " ." + new Date().toLocaleString() + " -> ";
        if (Q.ff)
            infoZone.textContent = message;
        else
            infoZone.innerText = message;
        timeZone.className = this.debugStyleClassTime;
        infoZone.className = this.debugStyleClassInfo;
        obj.appendChild(rowCount);
        obj.appendChild(timeZone);
        obj.appendChild(infoZone);
        this.debugZone.appendChild(obj);
        this.debugZone.scrollTop = this.debugZone.scrollHeight;
        // 下面代码有缺点仅参考
        // this.debugZone.insertBefore(obj, this.debugZone.firstChild);
        // obj.scrollIntoView();
    }
}
Q.U = {}
Q.U.zIndex = 2000;
Q.U.setTimeout = function(callback, timeout, args) {
    var as = Array.prototype.slice.call(arguments, 2);
    var pp = function() {
        callback.apply(null, as);
    }
    setTimeout(pp, timeout);
}
Q.U.getXmlRequest = function() {
    var req = null;
    try {
        req = new XMLHttpRequest();
    } catch (e) {
        var xmlVersions = new Array('Microsoft.XMLHTTP', 'Msxml2.XMLHTTP','Msxml2.XMLHTTP.3.0');
        for ( var i = 0; i < xmlVersions.length && !req; i++) {
            try {
                req = new ActiveXObject(xmlVersions[i]);
            } catch (e) {
                Q.debug(e);
            }
        }
    }
    return req;
}
// 获得一个目标的客户端坐标
Q.U.getPosition = function(obj) {
    if (obj == null) return null;
    var point = new Object();
    point.x = obj.offsetLeft;
    point.y = obj.offsetTop;
    while(obj = obj.offsetParent){
        point.x += obj.offsetLeft;
        point.y += obj.offsetTop;
    }
    return point;
}
// 设置目标的客户端坐标为x,y
Q.U.setPosition = function(srcObj, x, y) {
    Q.debug("set position to x=" + x + ", y=" + y);
    srcObj.style.left = x + "px";
    srcObj.style.top = y + "px";
}
// 设置目标srcObj的客户端坐标到另一个目标disObj的客户端坐标, offsetX, offsetY指定在disObj这个位置上的x,y偏移值(可为null)
Q.U.setPositionToObj = function(srcObj, disObj, offsetX, offsetY) {
    var pos = Q.U.getPosition(disObj);
    if (offsetX != null) pos.x += offsetX;
    if (offsetY != null) pos.y += offsetY;
    Q.U.setPosition(srcObj, pos.x, pos.y);
}
//table -> 空的table,e.g. table = document.createElement("table"); 函数返回表格的列矩阵,通过arr[row][column]访问表格各列
Q.U.createTable = function (table, rows, columns) {
    var arr = new Array();
    var row;
    for (var i = 0; i < rows; i++) {
        arr[i] = new Array(columns);
        row = table.insertRow(i);
        for (var n = 0; n < columns; n++)
            arr[i][n] = row.insertCell(n);
    }
    return arr;
}
Q.U.createTableAsObject = function (table, rows, columns) {
    var obj = new Table();
    for (var i = 0; i < rows; i++) {
        obj.row[i] = table.insertRow(i);
        obj.column[i] = new Array();
        for (var n = 0; n < columns; n++)
            obj.column[i][n] = obj.row[i].insertCell(n);
    }
    return obj;
    function Table() {
        this.row = new Array(); 	// 行数组，一维
        this.column = new Array();	// 列数组，二维
    }
}
// 获取当前视窗（可视部分）的宽度
Q.U.getViewportWidth = function(){
    if (window.innerWidth != window.undefined) return window.innerWidth;
    if (document.compatMode == 'CSS1Compat') return document.documentElement.clientWidth;
    if (document.body) return document.body.clientWidth;
    return window.undefined;
}
// 获取当前视窗（可视部分）的高度
Q.U.getViewportHeight = function(){
    if (window.innerHeight != window.undefined) return window.innerHeight;
    if (document.compatMode == 'CSS1Compat') return document.documentElement.clientHeight;
    if (document.body) return document.body.clientHeight;
    return window.undefined;
}
// -------------------------------------------- Public but ref above
Q.U.getEvent = function() {
    var event = findEvent();
    return event;
	
    function findEvent() {
        if(Q.ie) return window.event;
        var fun = findEvent.caller;
        var count = 0;
        while(fun != null && count < 50){
            var arg0 = fun.arguments[0];
            if(arg0){
                if((arg0.constructor == Event) || (typeof(arg0) == "object" && arg0.preventDefault && arg0.stopPropagation))
                    return arg0;
            }
            fun = fun.caller;
            count++;
        }
        return null;
    }
}
//为目标控件添加事件响应 e.g. Q.U.attachEvent("mydiv", "onclick", function(){myfun(arg1, arg2, arg...)});
Q.U.attachEvent = function(id, type, fun) {
    var target = Q.get(id);
    target = (target != null ? target : document);
    if (target.addEventListener) {
        target.addEventListener(type.substring(2), fun, false);
    } else if (target.attachEvent) {
        target.attachEvent(type, fun);
    } else {
        target['' + type] = fun;
    }
}
Q.U.detachEvent = function(id, type, fun) {
    var target = (id == null ? document : Q.get(id));
    if (target.removeEventListener) {
        target.removeEventListener(type.substring(2), fun, false);
    } else if (target.detachEvent) {
        target.detachEvent(type, fun);
    } else {
        target['' + type] = "";
    }
}
//设置不透明度，opaque=[0.0~1.0]
Q.U.setOpaque = function(id, opaque) {
    var obj = Q.get(id);
    if (obj != null) {
        if (Q.ie)
            obj.style.filter = "alpha(opacity=" + opaque * 100 + ")";
        else 
            obj.style.opacity = opaque;
    }
}
// 渐隐功能，传递某个界面组件的id即可
Q.U.toHidden = function(id, opaque) {
    opaque = (opaque != null ? opaque : 1);
    Q.U.setOpaque(id, opaque);
    if (opaque <= 0) {
        Q.get(id).style.display = "none";
        return;
    } else {
        Q.U.setTimeout(Q.U.toHidden, 20, id, (opaque - 0.1));
    }
}
Q.U.toShow = function(id, alpha) {
    alpha = (alpha != null ? alpha : 0);
    var obj = Q.get(id);
    if (obj != null) {
        if (obj.style.display == "none")
            obj.style.display = "";
        if (Q.ie)
            obj.style.filter = "alpha(opacity=" + alpha * 100 + ")";
        else
            obj.style.opacity = alpha;
    }
    if (alpha < 1)
        Q.U.setTimeout(Q.U.toShow, 50, id, (alpha + 0.1));
}
// 拖动功能,如果parentId存在，则拖动整个parentId, 否则只拖动自己
// 注:在IE下必须在Object完全载入页面之后才可以调用toEnableDrag,否则会出现以下错误：
// Unable to modify the parent container element before the child element is closed
Q.U.toEnableDrag = function(id, parentId) {
    var dragObj = null;
    var moveObj = null;
    dragObj = Q.get(id);
    moveObj = Q.get(parentId != null ? parentId : id);
    moveObj.style.zIndex = Q.U.zIndex++;
    moveObj.style.position = "absolute";
    moveObj.style.cursor = "move";
    moveObj.offsetX = 0;
    moveObj.offsetY = 0;
    event_onmouseup = function(event) {
        document.onmousemove = "";
        Q.U.detachEvent(null, "onmouseup", event_onmouseup);
    }
    dragObj.onmousedown = function(event) {
        event = event ? event : window.event;
        moveObj.offsetX = event.clientX - moveObj.offsetLeft;
        moveObj.offsetY = event.clientY - moveObj.offsetTop;
        document.onmousemove = function(event) {
            event = event ? event : window.event;
            moveObj.style.left = event.clientX - moveObj.offsetX + "px";
            moveObj.style.top = event.clientY - moveObj.offsetY + "px";
        }
        Q.U.attachEvent(null, "onmouseup", event_onmouseup);
    } //让移动窗口在鼠标down上去的时候能够显示在最前
    Q.U.attachEvent(moveObj, "onmousedown", function(){moveObj.style.zIndex = Q.U.zIndex++;});
}
Q.U.getElementSize = function(id) {
    var com = Q.get(id);
    var result = new Array(2);
    var tempW = com.style.width;
    var tempH = com.style.height;
    result[0] = (tempW != "" ? tempW.substring(0, tempW.length - 2) : null);
    result[1] = (tempH != "" ? tempH.substring(0, tempH.length - 2) : null);
    if (result[0] == null || result[1] == null) {
        var hide = (com.style.display == "none");
        if (hide) com.style.display = "";
        if (result[0] == null) result[0] = com.offsetWidth ;
        if (result[1] == null) result[1] = com.offsetHeight;
        if (hide) com.style.display = "none";
    }
    if (result[0] != null) result[0] = parseInt(result[0], 10);
    if (result[1] != null) result[1] = parseInt(result[1], 10);
    return result;
}
Q.U.getMousePosition = function() {
    var point = new Object();
    var event = Q.U.getEvent();
    if (!event)
        return null;
    if(event.pageX || event.pageY){ // FF
        point.x = event.pageX;
        point.y = event.pageY;
    } else {
        // document.documentElement 代替 document.body,避免在xhtml下无效，
        point.x = event.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft;
        point.y = event.clientY + document.documentElement.scrollTop - document.documentElement.clientTop;
    }
    return point;
}
Q.U.display = function(obj) {
    var target = Q.get(obj);
    if (target) target.style.display = (target.style.display == "none" ? "" : "none");
}
Q.U.open = function(obj) {
    var target = Q.get(obj);
    if (target) target.style.display = "";
}
Q.U.close = function(obj) {
    var target = Q.get(obj);
    if (target) target.style.display = "none";
}
Q.U.isVisible = function(obj) {
    var target = Q.get(obj);
    return (target != null && target.style.display != "none");
}
// escape不编码字符69：*，+，-，.，/，@，_，0-9，a-z，A-Z
// encodeURI不编码字符82：!，#，$，&，'，(，)，*，+，,，-，.，/，:，;，=，?，@，_，~，0-9，a-z，A-Z
// encodeURIComponent不编码字符71：!， '，(，)，*，-，.，_，~，0-9，a-z，A-Z
Q.U.encodeURI = function(val) {
    var v = encodeURIComponent(val);
    return v;
}
Q.U.getDocument = function() {
    return (document.compatMode == 'CSS1Compat' ? document.documentElement : document.body);
}
// move obj to x,y; time -> total time to use(millisecond); callback define a function
Q.U.move = function(obj, x, y, time, callback,
    timeout, sx, sy, xAdd, yAdd, xAmount, yAmount, xOk, yOk, step, stepCount) {
    if (!time) time = 200;
    if (!timeout) timeout = 10;
    if (!stepCount) stepCount = 0;
    if (sx == null || sy == null) {
        var s = Q.U.getPosition(obj);
        sx = s.x;
        sy = s.y;
        xAdd = sx < x;
        yAdd = sy < y;
        xOk = yOk = false;
        // 计算x,y增量 xAmount, yAmount
        step = time / timeout; 	// step
        var xd = x - sx; 		// distance from sx to x
        var yd = y - sy; 		// distance from sy to y
        xAmount = xd / step;
        yAmount = yd / step;
        Q.debug("Q.U.move, step=" + step + ", x=" + x + ", y=" + y + ", sx=" + sx + ", sy=" + sy + ", xAmount=" + xAmount + ", yAmount=" + yAmount);
    }
    xOk = xAdd ? sx >= x : sx <= x;
    yOk = yAdd ? sy >= y : sy <= y;
    if (!xOk) sx += xAmount;
    if (!yOk) sy += yAmount;
    // xAmount,yAmount的计算可能存在误差而导致无限loop
    stepCount++;
    if ((stepCount > step) || (xOk && yOk)) {
        if (typeof(callback) == "function")
            callback.apply();
        return;
    }
    Q.U.setPosition(obj, sx, sy);
    Q.U.setTimeout(Q.U.move, timeout,
        obj, x, y, time, callback,
        timeout, sx, sy, xAdd, yAdd, xAmount, yAmount, xOk, yOk, step, stepCount);
}
